#ifdef WIN32
#include <windows.h>
#elif LINUX
#include <pthread.h>
#endif

/* libc */
#include <stdio.h>
#include <unistd.h>
#include <process.h>

/* ptp */
#include "hal/interval_timer_hal.h"
#include "hcpp/ptp2_task_queue.h"

/* thread */


/* millisecond * (second * minute * hour * day) = day */
#define TIMER_0_PERIOD  10
#define DAY_FACTOR      (1000 * 60 * 60 * 24)
#define SECOND_FACTOR   (1000)

#ifdef LINUX
static pthread_t timer_thread;
#endif
#ifdef WIN32
HANDLE interval_timer_handle;
#endif


void interval_timer_hal_thread(void *context);

static volatile uint32_t day;
static volatile uint32_t day_fraction;
static volatile uint32_t sec;
static volatile uint32_t sec_fraction;
static volatile uint32_t msec;

/* lwip timer function */
uint32_t
sys_now(void)
{
    return msec;
}



/**
 * @brief   interrupt service routine
 *
 * @param   context     not used
 */
void
interval_timer_hal_thread(void *context)
{
    while (true) {
        usleep(TIMER_0_PERIOD * 1000);

        msec         += TIMER_0_PERIOD;
        sec_fraction += TIMER_0_PERIOD;
        day_fraction += TIMER_0_PERIOD;
        if (day_fraction >= DAY_FACTOR) {
            day          += 1;
            day_fraction -= DAY_FACTOR;
        }

        if (sec_fraction >= SECOND_FACTOR) {
            sec          += 1;
            sec_fraction -= SECOND_FACTOR;
        }

        /* tell queue the current time */
        ptp2_task_queue_tick(PTP2_TASK_QUEUE(), msec);
    }

    //return NULL;
}

/**
 * @brief   interval timer init
 *
 * @return  returns true if everything did well, false otherwise
 */
bool
interval_timer_hal_init(void)
{
    day             = 0;
    day_fraction    = 0;
    sec             = 0;
    sec_fraction    = 0;
    msec            = 0;

#ifdef LINUX
    pthread_create(&timer_thread, NULL, interval_timer_hal_thread, NULL);
#endif
#ifdef WIN32
    unsigned long   dw_interval_timer_id;              // thread id    ONLY FOR WIN95/98/ME
    CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)interval_timer_hal_thread,NULL,0,&dw_interval_timer_id);
#endif
    return true;
}

uint32_t
interval_timer_hal_get_miliseconds(void)
{
    return msec;
}

uint32_t
interval_timer_hal_get_seconds(void)
{
    return sec;
}

uint32_t
interval_timer_hal_get_second_fraction(void)
{
    return sec_fraction;
}

uint32_t
interval_timer_hal_get_days(void)
{
    return day;
}

